#include "elfmodel.h"
#include <QStandardItem>
#include <QFileInfo>

ElfModel::ElfModel(QObject *parent)
    : QStandardItemModel(parent) {
    setHorizontalHeaderLabels({"ELF Structure"});
}

void ElfModel::loadElf(const QString& filename) {
    clear();
    m_parser.reset(new ElfParser(filename));
    
    if (m_parser->parse()) {
        populateModel();
    }
}

void ElfModel::clear() {
    QStandardItemModel::clear();
    setHorizontalHeaderLabels({"ELF Structure"});
    m_parser.reset();
}

void ElfModel::populateModel() {
    if (!m_parser || !m_parser->isValid()) {
        return;
    }
    
    addHeaderItem();
    addProgramHeadersItem();
    addSectionHeadersItem();
    addSymbolsItem();
    addStringsItem();
}

void ElfModel::addHeaderItem() {
    QStandardItem *headerItem = new QStandardItem("ELF Header");
    headerItem->setData("header", Qt::UserRole);
    
    const ElfHeader& header = m_parser->header();
    
    headerItem->appendRow(new QStandardItem(QString("Type: %1").arg(header.type)));
    headerItem->appendRow(new QStandardItem(QString("Machine: %1").arg(header.machine)));
    headerItem->appendRow(new QStandardItem(QString("Entry: 0x%1").arg(header.entry, 0, 16)));
    headerItem->appendRow(new QStandardItem(QString("Program Headers: %1").arg(header.phnum)));
    headerItem->appendRow(new QStandardItem(QString("Section Headers: %1").arg(header.shnum)));
    
    appendRow(headerItem);
}

void ElfModel::addProgramHeadersItem() {
    QStandardItem *phItem = new QStandardItem("Program Headers");
    phItem->setData("program", Qt::UserRole);
    
    const QVector<ProgramHeader>& headers = m_parser->programHeaders();
    
    for (int i = 0; i < headers.size(); ++i) {
        const ProgramHeader& ph = headers[i];
        QStandardItem *item = new QStandardItem(QString("[%1] Type: %2").arg(i).arg(ph.type));
        item->setData(i, Qt::UserRole + 1);
        item->setData("program_item", Qt::UserRole);
        
        item->appendRow(new QStandardItem(QString("Offset: 0x%1").arg(ph.offset, 0, 16)));
        item->appendRow(new QStandardItem(QString("Virtual Address: 0x%1").arg(ph.vaddr, 0, 16)));
        item->appendRow(new QStandardItem(QString("Physical Address: 0x%1").arg(ph.paddr, 0, 16)));
        item->appendRow(new QStandardItem(QString("File Size: %1").arg(ph.filesz)));
        item->appendRow(new QStandardItem(QString("Memory Size: %1").arg(ph.memsz)));
        item->appendRow(new QStandardItem(QString("Flags: 0x%1").arg(ph.flags, 0, 16)));
        item->appendRow(new QStandardItem(QString("Alignment: %1").arg(ph.align)));
        
        phItem->appendRow(item);
    }
    
    appendRow(phItem);
}

void ElfModel::addSectionHeadersItem() {
    QStandardItem *shItem = new QStandardItem("Section Headers");
    shItem->setData("section", Qt::UserRole);
    
    const QVector<SectionHeader>& headers = m_parser->sectionHeaders();
    
    for (int i = 0; i < headers.size(); ++i) {
        const SectionHeader& sh = headers[i];
        QStandardItem *item = new QStandardItem(QString("[%1] %2").arg(i).arg(sh.sh_name));
        item->setData(i, Qt::UserRole + 1);
        item->setData("section_item", Qt::UserRole);
        
        item->appendRow(new QStandardItem(QString("Type: %1").arg(sh.type)));
        item->appendRow(new QStandardItem(QString("Address: 0x%1").arg(sh.addr, 0, 16)));
        item->appendRow(new QStandardItem(QString("Offset: 0x%1").arg(sh.offset, 0, 16)));
        item->appendRow(new QStandardItem(QString("Size: %1").arg(sh.size)));
        item->appendRow(new QStandardItem(QString("Link: %1").arg(sh.link)));
        item->appendRow(new QStandardItem(QString("Info: 0x%1").arg(sh.info, 0, 16)));
        item->appendRow(new QStandardItem(QString("Alignment: %1").arg(sh.align)));
        item->appendRow(new QStandardItem(QString("Entry Size: %1").arg(sh.entsize)));
        
        shItem->appendRow(item);
    }
    
    appendRow(shItem);
}

void ElfModel::addSymbolsItem() {
    QStandardItem *symItem = new QStandardItem("Symbols");
    symItem->setData("symbol", Qt::UserRole);
    
    const QVector<SymbolEntry>& symbols = m_parser->symbols();
    
    for (int i = 0; i < symbols.size(); ++i) {
        const SymbolEntry& sym = symbols[i];
        QStandardItem *item = new QStandardItem(QString("[%1] %2").arg(i).arg(sym.nameStr));
        item->setData(i, Qt::UserRole + 1);
        item->setData("symbol_item", Qt::UserRole);
        
        item->appendRow(new QStandardItem(QString("Value: 0x%1").arg(sym.value, 0, 16)));
        item->appendRow(new QStandardItem(QString("Size: %1").arg(sym.size)));
        item->appendRow(new QStandardItem(QString("Type: %1").arg(sym.typeString())));
        item->appendRow(new QStandardItem(QString("Bind: %1").arg(sym.bindString())));
        item->appendRow(new QStandardItem(QString("Visibility: %1").arg(sym.visibilityString())));
        item->appendRow(new QStandardItem(QString("Section: %1").arg(sym.shndx)));
        
        symItem->appendRow(item);
    }
    
    appendRow(symItem);
}

void ElfModel::addStringsItem() {
    QStandardItem *strItem = new QStandardItem("Strings");
    strItem->setData("string", Qt::UserRole);
    
    const QVector<QString>& strings = m_parser->strings();
    
    for (int i = 0; i < strings.size() && i < 100; ++i) { // Limit to 100 strings
        QStandardItem *item = new QStandardItem(strings[i]);
        item->setData(i, Qt::UserRole + 1);
        item->setData("string_item", Qt::UserRole);
        strItem->appendRow(item);
    }
    
    if (strings.size() > 100) {
        strItem->appendRow(new QStandardItem(QString("... and %1 more strings").arg(strings.size() - 100)));
    }
    
    appendRow(strItem);
}

QString ElfModel::toJson() const {
    return m_parser ? m_parser->toJson() : "{}";
}

QString ElfModel::toText() const {
    return m_parser ? m_parser->toText() : "No ELF file loaded";
}
